/*
 * token.c
 *
 *  Created on: 2013-5-8
 *      Author: xkaying
 */

#include <stdlib.h>
#include <string.h>

#include "token.h"
#include "../parser/symboltable.h"
//部分关键字

Token *TokenInit(int tokentype)
{
	Token *ptoken;
	ptoken = (Token*) malloc(sizeof(Token));
	ptoken->type = tokentype;
	ptoken->name = 0;
	ptoken->str = 0;
	ptoken->len = 0;
	return ptoken;
}

unsigned time33(char *str, int len)
{
	unsigned long hash = 0;
	for (int i = 0; i < len; i++) {
		hash = hash * 33 + (unsigned long) str[i];
	}
	return hash;
}

int tstrcmp(char *str, char *name, int len)
{
	int i;
	int nlen;
	nlen = strlen(name);
	if (nlen == len) {
		for (i = 0; i < len; i++) {
			if (str[i] != name[i]) {
				return 1;
			}
		}
		return 0;
	}
	return nlen > len ? 1 : -1;
}

void TokenKeyCheck(Token *ptoken)
{
	if (ptoken->len > 1 && ptoken->len < 15) {
		//说明可能是关键字
		int hash;
		hash = time33(ptoken->str, ptoken->len) % 64;
		switch (hash)
		{
			case 44: {
				if (!tstrcmp(ptoken->str, "package", ptoken->len)) {
					ptoken->type = TokenKey_PACKAGE;
					return;
				}
				if (!tstrcmp(ptoken->str, "operator", ptoken->len)) {
					ptoken->type = TokenKey_OPERATOR;
					return;
				}
				break;
			}
			case 59: {
				if (!tstrcmp(ptoken->str, "import", ptoken->len)) {
					ptoken->type = TokenKey_IMPORT;
					return;
				}
				if (!tstrcmp(ptoken->str, "private", ptoken->len)) {
					ptoken->type = TokenKey_PRIVATE;
					return;
				}
				break;
			}
			case 53: {
				if (!tstrcmp(ptoken->str, "enum", ptoken->len)) {
					ptoken->type = TokenKey_ENUM;
					return;
				}
				break;
			}
			case 49: {
				if (!tstrcmp(ptoken->str, "interface", ptoken->len)) {
					ptoken->type = TokenKey_INTERFACE;
					return;
				}
				break;
			}
			case 54: {
				if (!tstrcmp(ptoken->str, "class", ptoken->len)) {
					ptoken->type = TokenKey_CLASS;
					return;
				}
				break;
			}
			case 6: {
				if (!tstrcmp(ptoken->str, "function", ptoken->len)) {
					ptoken->type = TokenKey_FUNCTION;
					return;
				}
				if (!tstrcmp(ptoken->str, "constpublic", ptoken->len)) {
					ptoken->type = TokenKey_CONSTPUBLIC;
					return;
				}
				break;
				break;
			}
			case 31: {
				if (!tstrcmp(ptoken->str, "public", ptoken->len)) {
					ptoken->type = TokenKey_PUBLIC;
					return;
				}
				if (!tstrcmp(ptoken->str, "inline", ptoken->len)) {
					ptoken->type = TokenKey_INLINE;
					return;
				}
				break;
			}
			case 10: {
				if (!tstrcmp(ptoken->str, "protected", ptoken->len)) {
					ptoken->type = TokenKey_PROTECTED;
					return;
				}
				if (!tstrcmp(ptoken->str, "final", ptoken->len)) {
					ptoken->type = TokenKey_FINAL;
					return;
				}
				break;
			}

			case 2: {
				if (!tstrcmp(ptoken->str, "constprivate", ptoken->len)) {
					ptoken->type = TokenKey_CONSTPRIVATE;
					return;
				}
				break;
			}
			case 17: {
				if (!tstrcmp(ptoken->str, "constprotected", ptoken->len)) {
					ptoken->type = TokenKey_CONSTPROTECTED;
					return;
				}
				break;
			}
			case 7: {
				if (!tstrcmp(ptoken->str, "virtual", ptoken->len)) {
					ptoken->type = TokenKey_VIRTUAL;
					return;
				}
				break;
			}
			case 47: {
				if (!tstrcmp(ptoken->str, "if", ptoken->len)) {
					ptoken->type = TokenKey_IF;
					return;
				}
				break;
			}
			case 41: {
				if (!tstrcmp(ptoken->str, "else", ptoken->len)) {
					ptoken->type = TokenKey_ELSE;
					return;
				}
				break;
			}
			case 25: {
				if (!tstrcmp(ptoken->str, "while", ptoken->len)) {
					ptoken->type = TokenKey_WHILE;
					return;
				}
				break;
			}
			case 50: {
				if (!tstrcmp(ptoken->str, "switch", ptoken->len)) {
					ptoken->type = TokenKey_SWITCH;
					return;
				}
				break;
			}
			case 28: {
				if (!tstrcmp(ptoken->str, "case", ptoken->len)) {
					ptoken->type = TokenKey_CASE;
					return;
				}
				break;
			}
			case 20: {
				if (!tstrcmp(ptoken->str, "throw", ptoken->len)) {
					ptoken->type = TokenKey_THROW;
					return;
				}
				break;
			}
			case 3: {
				if (!tstrcmp(ptoken->str, "catch", ptoken->len)) {
					ptoken->type = TokenKey_CATCH;
					return;
				}
				break;
			}
			case 32: {
				if (!tstrcmp(ptoken->str, "return", ptoken->len)) {
					ptoken->type = TokenKey_RETURN;
					return;
				}
				break;
			}
			case 5: {
				if (!tstrcmp(ptoken->str, "continue", ptoken->len)) {
					ptoken->type = TokenKey_CONTINUE;
					return;
				}
				break;
			}
			case 37: {
				if (!tstrcmp(ptoken->str, "break", ptoken->len)) {
					ptoken->type = TokenKey_BREAK;
					return;
				}
				break;
			}
			case 56: {
				if (!tstrcmp(ptoken->str, "foreach", ptoken->len)) {
					ptoken->type = TokenKey_FOREACH;
					return;
				}
				break;
			}
			case 39: {
				if (!tstrcmp(ptoken->str, "for", ptoken->len)) {
					ptoken->type = TokenKey_FOR;
					return;
				}
				break;
			}
			default:
				break;
		}
	}
	ptoken->name = SymbolTablePush(ptoken->str, ptoken->len);
}
